package com.zhihaihe.file.commponent;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qiwenshare.common.constant.FileConstant;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.ufop.util.UFOPUtils;
import com.zhihaihe.file.mapper.UserFileMapper;
import com.zhihaihe.file.pojo.*;
import com.zhihaihe.file.service.IShareFileService;
import com.zhihaihe.file.service.IShareService;
import com.zhihaihe.file.service.IUserFileService;
import com.zhihaihe.file.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 文件逻辑处理组件
 */
@Slf4j
@Component
public class FileDealComp {
    @Autowired
    IUserFileService userFileService;
    @Autowired
    UserFileMapper userFileMapper;
    @Autowired
    IUserService userService;
    @Autowired
    IShareService shareService;
    @Autowired
    IShareFileService shareFileService;
    /**
     * 还原父文件路径
     *
     * 1、回收站文件还原操作会将文件恢复到原来的路径下,当还原文件的时候，如果父目录已经不存在了，则需要把父母录给还原
     * 2、上传目录
     *
     * @param filePath
     * @param sessionUserId
     */
    public void restoreParentFilePath(String filePath, Long sessionUserId) {
        // 加锁，防止并发情况下有重复创建目录情况
        Lock lock = new ReentrantLock();
        lock.lock();
        String parentFilePath = UFOPUtils.getParentPath(filePath);
        while(parentFilePath.contains("/")) {
            String fileName = parentFilePath.substring(parentFilePath.lastIndexOf("/") + 1);
            parentFilePath = UFOPUtils.getParentPath(parentFilePath);

            LambdaQueryWrapper<UserFileBean> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(UserFileBean::getFilePath, parentFilePath + FileConstant.pathSeparator)
                    .eq(UserFileBean::getFileName, fileName)
                    .eq(UserFileBean::getDeleteFlag, 0)
                    .eq(UserFileBean::getIsDir, 1)
                    .eq(UserFileBean::getUserId, sessionUserId);
            List<UserFileBean> userFileList = userFileMapper.selectList(lambdaQueryWrapper);
            if (userFileList.size() == 0) {
                UserFileBean userFile = new UserFileBean();
                userFile.setUserId(sessionUserId);
                userFile.setFileName(fileName);
                userFile.setFilePath(parentFilePath + FileConstant.pathSeparator);
                userFile.setDeleteFlag(0);
                userFile.setIsDir(1);
                userFile.setUploadTime(DateUtil.getCurrentTime());

                userFileMapper.insert(userFile);
            }
        }
        lock.unlock();
    }

    /**
     * 删除重复的子目录文件
     *
     * 当还原目录的时候，如果其子目录在文件系统中已存在，则还原之后进行去重操作
     * @param filePath
     * @param sessionUserId
     */
    public void deleteRepeatSubDirFile(String filePath, Long sessionUserId) {
        log.debug("删除子目录："+filePath);
        LambdaQueryWrapper<UserFileBean> lambdaQueryWrapper = new LambdaQueryWrapper<>();

        LambdaQueryWrapper<UserFileBean> having = lambdaQueryWrapper.select(UserFileBean::getFileName, UserFileBean::getFilePath)
                .likeRight(UserFileBean::getFilePath, filePath)
                .eq(UserFileBean::getIsDir, 1)
                .eq(UserFileBean::getDeleteFlag, 0)
                .eq(UserFileBean::getUserId, sessionUserId)
                .groupBy(UserFileBean::getFilePath, UserFileBean::getFileName)
                .having("count(fileName) >= 2");
        List<UserFileBean> repeatList = userFileMapper.selectList(lambdaQueryWrapper);

        for (UserFileBean userFile : repeatList) {
            LambdaQueryWrapper<UserFileBean> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper1.eq(UserFileBean::getFilePath, userFile.getFilePath())
                    .eq(UserFileBean::getFileName, userFile.getFileName())
                    .eq(UserFileBean::getDeleteFlag, "0");
            List<UserFileBean> userFiles = userFileMapper.selectList(lambdaQueryWrapper1);
            for (int i = 0; i < userFiles.size() - 1; i ++) {
                userFileMapper.deleteById(userFiles.get(i).getUserFileId());
            }
        }
    }

    /**
     * 获取重复文件名
     * 场景1: 文件还原时，在 savefilePath 路径下，保存 测试.txt 文件重名，则会生成 测试(1).txt
     * 场景2： 上传文件时，在 savefilePath 路径下，保存 测试.txt 文件重名，则会生成 测试(1).txt
     * @param userFile
     * @param savefilePath
     * @return
     */
    public String getRepeatFileName(UserFileBean userFile, String savefilePath) {
        String fileName = userFile.getFileName();
        String extendName = userFile.getExtendName();
        Integer deleteFlag = userFile.getDeleteFlag();
        Long userId = userFile.getUserId();
        int isDir = userFile.getIsDir();
        LambdaQueryWrapper<UserFileBean> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(UserFileBean::getFilePath, savefilePath)
                .eq(UserFileBean::getDeleteFlag, deleteFlag)
                .eq(UserFileBean::getUserId, userId)
                .eq(UserFileBean::getFileName, fileName)
                .eq(UserFileBean::getIsDir, isDir);
        if (userFile.getIsDir() == 0) {
            lambdaQueryWrapper.eq(UserFileBean::getExtendName, extendName);
        }
        List<UserFileBean> list = userFileMapper.selectList(lambdaQueryWrapper);
        if (list == null) {
            return fileName;
        }
        if (list.isEmpty()) {
            return fileName;
        }
        int i = 0;

        while (list != null && !list.isEmpty()) {
            i++;
            LambdaQueryWrapper<UserFileBean> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper1.eq(UserFileBean::getFilePath, savefilePath)
                    .eq(UserFileBean::getDeleteFlag, deleteFlag)
                    .eq(UserFileBean::getUserId, userId)
                    .eq(UserFileBean::getFileName, fileName + "(" + i + ")")
                    .eq(UserFileBean::getIsDir, isDir);
            if (userFile.getIsDir() == 0) {
                lambdaQueryWrapper1.eq(UserFileBean::getExtendName, extendName);
            }
            list = userFileMapper.selectList(lambdaQueryWrapper1);
        }

        return fileName + "(" + i + ")";

    }
    /**
     * 根据用户传入的参数，判断是否有下载或者预览权限
     * @return
     */
    public boolean checkAuthDownloadAndPreview(String shareBatchNum,
                                               String extractionCode,
                                               String token,
                                               long userFileId) {
        log.debug("权限检查开始：shareBatchNum:{}, extractionCode:{}, token:{}, userFileId{}" , shareBatchNum, extractionCode, token, userFileId);
        UserFileBean userFile = userFileService.getById(userFileId);
        log.debug(JSON.toJSONString(userFile));
        if ("undefined".equals(shareBatchNum)  || StringUtils.isEmpty(shareBatchNum)) {

            UserBean sessionUserBean = userService.getUserBeanByToken(token);
            log.debug(JSON.toJSONString("当前登录session用户：" + sessionUserBean));
            if (sessionUserBean == null) {
                return false;
            }
            log.debug("文件所属用户id：" + userFile.getUserId());
            log.debug("登录用户id:" + sessionUserBean.getUserId());
            if (userFile.getUserId().longValue() != sessionUserBean.getUserId().longValue()) {
                log.info("用户id不一致，权限校验失败");
                return false;
            }
        } else {
            Map<String, Object> param = new HashMap<>();
            param.put("shareBatchNum", shareBatchNum);
            List<Share> shareList = shareService.listByMap(param);
            //判断批次号
            if (shareList.size() <= 0) {
                log.info("分享批次号不存在，权限校验失败");
                return false;
            }
            Integer shareType = shareList.get(0).getShareType();
            if (1 == shareType) {
                //判断提取码
                if (!shareList.get(0).getExtractionCode().equals(extractionCode)) {
                    log.info("提取码错误，权限校验失败");
                    return false;
                }
            }
            param.put("userFileId", userFileId);
            List<ShareFile> shareFileList = shareFileService.listByMap(param);
            if (shareFileList.size() <= 0) {
                log.info("用户id和分享批次号不匹配，权限校验失败");
                return false;
            }

        }
        return true;
    }

}
